﻿using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using dnAnalytics.Statistics;

namespace dnAnalytics.Tests.Statistics
{
    [TestFixture]
    public class StatisticsTests
    {
        private readonly IDictionary<string, StatTestData> mData = new Dictionary<string, StatTestData>();
        public StatisticsTests()
        {
            StatTestData lottery = new StatTestData("./TestData/NIST/Lottery.dat");
            mData.Add("lottery", lottery);
            StatTestData lew = new StatTestData("./TestData/NIST/Lew.dat");
            mData.Add("lew", lew);
            StatTestData mavro = new StatTestData("./TestData/NIST/Mavro.dat");
            mData.Add("mavro", mavro);
            StatTestData michelso = new StatTestData("./TestData/NIST/Michelso.dat");
            mData.Add("michelso", michelso);
            StatTestData numacc1 = new StatTestData("./TestData/NIST/NumAcc1.dat");
            mData.Add("numacc1", numacc1);
            StatTestData numacc2 = new StatTestData("./TestData/NIST/NumAcc2.dat");
            mData.Add("numacc2", numacc2);
            StatTestData numacc3 = new StatTestData("./TestData/NIST/NumAcc3.dat");
            mData.Add("numacc3", numacc3);
            StatTestData numacc4 = new StatTestData("./TestData/NIST/NumAcc4.dat");
            mData.Add("numacc4", numacc4);
        }
        
        [Test]
        [TestCase("lottery")]
        [TestCase("lew")]
        [TestCase("mavro")]
        [TestCase("michelso")]
        [TestCase("numacc1")]
        [TestCase("numacc2")]
        [TestCase("numacc3")]
        [TestCase("numacc4")]
        public void Mean(string dataSet)
        {
            StatTestData data = mData[dataSet];
            TestHelper.TestSignificantDigits(data.Mean, data.Data.Mean(), 15);
        }

        [Test]
        [TestCase("lottery")]
        [TestCase("lew")]
        [TestCase("mavro")]
        [TestCase("michelso")]
        [TestCase("numacc1")]
        [TestCase("numacc2")]
        [TestCase("numacc3")]
        [TestCase("numacc4")]
        public void NullableMean(string dataSet)
        {
            StatTestData data = mData[dataSet];
            TestHelper.TestSignificantDigits(data.Mean, data.DataWithNulls.Mean(), 15);
        }
        
        [Test]
        public void Mean_ThrowsArgumentNullException()
        {
            double[] data = null;
            Assert.Throws<ArgumentNullException>(() => dnAnalytics.Statistics.Statistics.Mean(data));
        }


        [Test]
        [TestCase("lottery", 15)]
        [TestCase("lew", 15)]
        [TestCase("mavro", 12)]
        [TestCase("michelso", 12)]
        [TestCase("numacc1", 15)]
        [TestCase("numacc2", 14)]
        [TestCase("numacc3", 9)]
        [TestCase("numacc4", 8)]
        public void StandardDeviation(string dataSet, int digits)
        {
            StatTestData data = mData[dataSet];
            TestHelper.TestSignificantDigits(data.StandardDeviation, data.Data.StandardDeviation(), digits);
        }

        [Test]
        [TestCase("lottery", 15)]
        [TestCase("lew", 15)]
        [TestCase("mavro", 12)]
        [TestCase("michelso", 12)]
        [TestCase("numacc1", 15)]
        [TestCase("numacc2", 14)]
        [TestCase("numacc3", 9)]
        [TestCase("numacc4", 8)]
        public void NullableStandardDeviation(string dataSet, int digits)
        {
            StatTestData data = mData[dataSet];
            TestHelper.TestSignificantDigits(data.StandardDeviation, data.DataWithNulls.StandardDeviation(), digits);
        }

        [Test]
        public void StandardDeviation_ThrowsArgumentNullException()
        {
            double[] data = null;
            Assert.Throws<ArgumentNullException>(() => dnAnalytics.Statistics.Statistics.StandardDeviation(data));
        }
    }
}
